import { Node, sys, tween, Tween, v3, Vec3 } from "cc";

export class AnimtorUtils {
    /**
     * 
     * @param node 节点
     * @param shakeDuration 震动时长
     * @param shakeStrength 震动强度 
     */
    public static startShake(node: Node, shakeDuration: number, shakeStrength: number) {
        const startTime = sys.now();
        const endTime = startTime + shakeDuration * 1000;
        node['oldPos'] = node['oldPos'] ? node['oldPos'] : node.getPosition();
        const originalPosition = node['oldPos']
        const shakeTween = tween(node)
            .call(() => {
                if (sys.now() < endTime) {
                    const randomX = (Math.random() - 0.5) * 2 * shakeStrength;
                    const randomY = (Math.random() - 0.5) * 2 * shakeStrength;
                    node.setPosition(
                        new Vec3(originalPosition.x + randomX, originalPosition.y + randomY, originalPosition.z)

                    );
                } else {
                    node.setPosition(originalPosition);
                    shakeTween.stop();
                }
            })
            .delay(0.01)
            .union()
            .repeatForever()
            .start();
    }
    /**
     * 缩放动画
    * @param {Node} node - 要缩放的节点
    * @param {number} scale - 缩放比例
    * @param {boolean} isLoop - 是否循环缩放
    */
    public static scale(node: Node, scale: number, isLoop: boolean) {
        const originalScale = node.getScale(); // 获取原始缩放值
        // 创建缩放动画
        const scaleTween = tween(node)
            .to(0.5, { scale: new Vec3(originalScale.x * scale, originalScale.y * scale, originalScale.z * scale) }) // 放大
            .to(0.5, { scale: originalScale }) // 恢复原始大小
            .call(() => {
                if (isLoop) {
                    scaleTween.start(); // 如果需要循环，重新开始动画
                }
            });
        scaleTween.start(); // 启动动画
    }
    //停止动画缩放动画，并且恢复到原始缩放值
    //停止动画缩放动画，并且恢复到原始缩放值
    public static stopScale(node: Node) {
        if (!node) return;
        const originalScale = node.getScale();
        Tween.stopAllByTarget(node);
        node.setScale(originalScale);
    }

    /**
     * 停止节点所有动画并恢复初始状态
     * @param node 目标节点
     */
    public static stopAllAnimations(node: Node) {
        if (!node) return;

        // 停止所有tween动画
        tween(node).stop();

        // 恢复初始属性（根据已有动画可能修改的属性）
        if (node['oldPos']) {
            node.setPosition(node['oldPos']);
            delete node['oldPos'];
        }
        node.setScale(node.getScale());
    }

    //上下移动并且缩放的动画
    //上下移动并且缩放的动画
    /**
     * 组合动画：上下移动+缩放
     * @param node 目标节点
     * @param amplitude 移动幅度（单位：像素）
     * @param duration 单次动画周期时长（单位：秒）
     * @param isLoop 是否循环播放
     */
    public static moveAndScale(node: Node, amplitude: number, duration: number, isLoop: boolean = true, delay: number = 0) {
        const originalPos = node.getPosition();
        const originalScale = node.getScale();
        node['moveScaleOriginal'] = node['moveScaleOriginal'] ? node['moveScaleOriginal'] : { pos: originalPos.clone(), scale: originalScale.clone() };

        // 修正后的动画序列（总时长保持duration）
        const combo = tween(node).delay(Math.random() * 0.3)
            // 第一阶段：上移+放大（1/3时间）
            .to(duration / 3, {
                position: new Vec3(originalPos.x, originalPos.y + amplitude, originalPos.z),
                scale: new Vec3(originalScale.x * 1.05, originalScale.y * 1.05, originalScale.z * 1.05)
            })
            // 第二阶段：下移+恢复缩放（1/3时间）
            .to(duration / 3, {
                position: new Vec3(originalPos.x, originalPos.y - amplitude, originalPos.z),
                scale: originalScale
            })
        // 设置循环模式
        if (isLoop) {
            combo.union().repeatForever();  // 永久循环
        }
        return combo
    }
    /**抛物线动画 */
    public static  parabolicMotion(info: obj) {
        console.log("info",info)
        const startTime = performance.now();
        const heightFactor = 3.5; // 用于调整抛物线最高点的系数，值越大最高点越高
        var duration = info.duration || 2000;
        function animate(currentTime) {
            const elapsedTime = currentTime - startTime;
            if (elapsedTime < duration) {
                const t = elapsedTime / duration;
                const x = info.start.x+ t * (info.end.x - info.start.x);
                const y = info.start.y + t * (info.end.y - info.start.y) - heightFactor * 400 * t * (t-1); // 调整后的抛物线效果
                info.runCallback && info.runCallback(v3(x, y, 0));
                requestAnimationFrame(animate);
            } else {
                info.runCallback && info.runCallback(v3(info.end.x, info.end.y, 0));
                info.endCallback && info.endCallback(info.args);
            }
        }
        requestAnimationFrame(animate);
    }
    /**
         * 停止移动缩放动画并恢复初始值
         * @param node 目标节点
         */
    public static stopMoveAndScale(node: Node) {
        if (!node || !node['moveScaleOriginal']) return;
        Tween.stopAllByTarget(node);
        node.setPosition(node['moveScaleOriginal'].pos);
        node.setScale(node['moveScaleOriginal'].scale);
        delete node['moveScaleOriginal'];
    }
}
interface obj { start:Vec3, end:Vec3, duration:number, runCallback?:Function, endCallback?:Function,args?:any }